package com.hp.bon.sgw.wh.channel.handler;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.BuzProcessorManager;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.core.channel.SoapChannel;
import com.hp.bon.sgw.core.channel.handler.IAsynCallHandler;
import com.hp.bon.sgw.threads.TaskManager;
import com.hp.bon.sgw.wh.bean.QueryBalanceResponse;
import com.hp.bon.sgw.wh.service.UserResourceConfigService;
import com.hp.bon.sgw.wh.utils.LogUtil;
import com.hp.bon.sgw.wh.utils.ResultCodeUtil;
import com.hp.ocs.diameter.message.*;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.simpleframework.http.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: QryBalanceRecordDetailHandle
 * @Description: 3.2.13余额变动明细查询 (下游DCC+新增webservice接口)
 */
public class QryBalanceRecordDetailHandle2 implements IAsynCallHandler {
	private static final Logger _log = LoggerFactory.getLogger(QryBalanceRecordDetailHandle2.class);

	private static final Object XmlMessage = null;

	private PrintStream printStream;
	private JSONObject requestObject;
    private long startTime;
    private Request request;
	private UserResourceConfigService userResourceConfigService ;
	public QryBalanceRecordDetailHandle2(PrintStream printStream, JSONObject requestObject, Request request, long startTime) {
		this.printStream = printStream;
		this.requestObject = requestObject;
        this.startTime = startTime;
        this.request = request;
	}

	@Override
	public int getProtocolType() {
		return 0;
	}

	@Override
	public void onCallResult(CallParam callParam) {
		XmlMessage ack = null;
		Object response = null;
		if (callParam.getResponse() != null) {
			_log.warn("getResponse():");
			response = callParam.getResponse();
		} else if (callParam.getRecvResponse() != null) {
			_log.warn("getRecvResponse():");
			response = callParam.getRecvResponse();
		}
		if (response == null) {
			int _retcodeTmp = callParam.getRetCode() == 3002 ? 11202 : callParam.getRetCode();
			ack = SoapChannel.createERRAnwser(callParam.getSessionId(), _retcodeTmp, callParam.getResultMsg());
			callParam.setServiceResultCode(_retcodeTmp);// 11203
		} else {
			if (response instanceof Message) {// CCA -> XML
				ack = BuzProcessorManager.getInstance().convertMessageToAck(callParam);
			} else if (response instanceof XmlMessage) {
				ack = (XmlMessage) response;
			} else {
				_log.warn("unknown response type:" + callParam.getResponse().getClass().getName());
			}
		}
		try {
			
			if (response instanceof Message) {
				_log.info("==========解析格式	 Message==============");
			}else if (response instanceof XmlMessage) {
				_log.info("==========解析格式	 XmlMessage==============");
			}
			String respXML = convertResponseString(response, callParam.getServiceResultCode());

			byte[] resp = respXML.getBytes("UTF-8");
			ack.setLength(resp.length);
			ack.setMsgTime(System.currentTimeMillis());
			printStream.write(resp);
			printStream.close();
			callParam.setResponse(ack);
//			if (callParam.getRetCode() == Constants.ResultCode.SUCCESS) {// 成功的消息，请求应答入库
//				MessageDetail detail = new MessageDetail();
//				detail.setBusinessCallId(callParam.getBussinessCallId());
//				detail.setSessionId(callParam.getSessionId());
//				detail.setServiceContextId(callParam.getServiceContextId());
//				detail.setMessageType(MessageType.WSA);
//				detail.setDetails(ack.getDATA());
//				detail.setMsgTime(new Date(ack.getMsgTime()));
//				detail.setOpType("send");
//				detail.setHostId(callParam.getUserName());
//				MessageDetailCacheManager.getInstance().add(detail);
//			}
            //记录到日志
            LogUtil.saveLogToABM(request,respXML,startTime);
			TaskManager.taskProcess(callParam);
            _log.info("http response(cfq) " + respXML);
		} catch (UnsupportedEncodingException e) {
			_log.info("convertResponseString UnsupportedEncodingException error,msg=" + e.getMessage());
		} catch (IOException e) {
			_log.info("convertResponseString IOException,msg=" + e.getMessage());
		}catch (Exception e) {
			e.printStackTrace();
			_log.error("convertResponseString IOException,msg=" + e.getMessage());
		}
	}
	

	
	
	/**
	 * 返回最终json格式数据
	 * @param answer
	 * @param serviceResultCode
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private String convertResponseString(Object answer, int serviceResultCode) {
		_log.error("QryBalanceRecordDetailHandle2 serviceResultCode = {}", serviceResultCode);
		Gson gson = new Gson();
		_log.info("ReturnBalanceHandle serviceResultCode = {}", serviceResultCode);
		// 返回json字符串最外层的map
		Map<String, Object> data = new HashMap<String, Object>();
		// json字符串中的ReturnPlanInfo节点，该节点为list
		List<Map<String, String>> returnPlanInfoList = new ArrayList<Map<String, String>>();
		
		if(11202 == serviceResultCode || answer == null ) {
			data.put("resultCode", "-1");
			data.put("resultMsg", "查询失败");
            String newCode = ResultCodeUtil.updateResultCode(data.get("resultCode"), userResourceConfigService.getValue("api_resultCode"), userResourceConfigService.getValue("api_defaultResult"));
            data.put("resultCode", newCode);
			return gson.toJson(data);
		}
		// 从下游解析返回信息中解析出来的数据，该数据和用户需要的数据并不相符，需要进行处理
		Map<String, Object> avpResultMap = getAvpsFromMessage((Message)answer);
		
		if (null == avpResultMap) {
			data.put("resultCode", "-1");
			data.put("resultMsg", "查询失败");
		}else if (serviceResultCode == 0) {
			data.put("resultCode", "0");
			data.put("resultMsg", "SUCCESS");
			data.putAll(avpResultMap);
		} else {
			data.put("resultCode", serviceResultCode);
			data.put("resultMsg", "查询失败");
		}
        String newCode = ResultCodeUtil.updateResultCode(data.get("resultCode"), userResourceConfigService.getValue("api_resultCode"), userResourceConfigService.getValue("api_defaultResult"));
        data.put("resultCode", newCode);
		return gson.toJson(data);
	}

	
	/**
	 * 从返回信息中解析AVP信息
	 * @param answer
	 * @return
	 */
	public Map<String, Object> getAvpsFromMessage(Message answer) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		List<Map<String, Object>> returnPlanInfos = new ArrayList<Map<String, Object>>();
		try {
			AVP serviceINformationAVP = answer.find(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP);
			AVP_Grouped serviceInfomationGroup;
			serviceInfomationGroup = new AVP_Grouped(serviceINformationAVP);
			AVP[] avps = serviceInfomationGroup.queryAVPs();
			for(AVP avp : avps){
				if(avp.code() == 20631 && avp.vendorID() == 81000){
					// Result节点
					//resultMap.put("Result", String.valueOf(new AVP_Unsigned32(avp).queryValue()));
				}else if(avp.code() == 90221 && avp.vendorID() == 81000){
					// BalanceRecordDetailInfo节点，下游返回信息中会有多个该节点
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("serviceId", "");
					map.put("billingCycleId", "");
					map.put("stateDate", "");
					map.put("balanceChangeType", "");
					map.put("balanceVal", "");
					map.put("beforeBalanceVal", "");
					map.put("afterBalanceVal", "");
					map.put("balanceIn", "");
					map.put("balanceOut", "");
					map.put("balanceEnd", "");
					map.put("balanceTypeFlag", "");
					map.put("balanceTypeName", "");
					map.put("accNbrDetail", "");
					AVP_Grouped returnPlanInfoGroup = new AVP_Grouped(avp);
					AVP serviceId = returnPlanInfoGroup.find(80135, Constants.DIAMETER_VENDOR_CT);
					if (serviceId != null) {//Payment_Serial_Nbr
						map.put("serviceId", new AVP_UTF8String(serviceId).queryValue());
					}
					AVP billingCycleId = returnPlanInfoGroup.find(5043, Constants.DIAMETER_VENDOR_CT);
					if (billingCycleId != null) {//Billing_Cycle
						map.put("billingCycleId", Long.valueOf(new AVP_UTF8String(billingCycleId).queryValue()));
					}
					AVP stateDate = returnPlanInfoGroup.find(80419, Constants.DIAMETER_VENDOR_CT);
					if (stateDate != null) {//stateDate
						map.put("stateDate", new AVP_UTF8String(stateDate).queryValue());
					}
					AVP balanceChangeType = returnPlanInfoGroup.find(90222, Constants.DIAMETER_VENDOR_CT);
					if (balanceChangeType != null) {//BalanceChangeType
						map.put("balanceChangeType", new AVP_Integer32(balanceChangeType).queryValue()+"");
					}
					AVP BalanceIn = returnPlanInfoGroup.find(90217, Constants.DIAMETER_VENDOR_CT);
					AVP BalanceOut = returnPlanInfoGroup.find(90218, Constants.DIAMETER_VENDOR_CT);
					if (BalanceIn != null && BalanceOut != null) {//BalanceIn+BalanceOut   90217+90218
						map.put("balanceVal", Long.valueOf((new AVP_Integer64(BalanceIn).queryValue()+new AVP_Integer64(BalanceOut).queryValue())+""));
					}
					if(BalanceIn != null) {
						map.put("balanceIn",  Long.valueOf(new AVP_Integer64(BalanceIn).queryValue()));
					}
					if(BalanceOut != null) {
						map.put("balanceOut",  Long.valueOf(new AVP_Integer64(BalanceOut).queryValue()));
					}
					AVP BalanceEnd = returnPlanInfoGroup.find(90219, Constants.DIAMETER_VENDOR_CT);
					if (BalanceEnd != null) {//BalanceEnd-(BalanceIn+BalanceOut)
						map.put("beforeBalanceVal", new AVP_Integer64(BalanceEnd).queryValue()-(new AVP_Integer64(BalanceIn).queryValue()+new AVP_Integer64(BalanceOut).queryValue()));
						map.put("afterBalanceVal", new AVP_Integer64(BalanceEnd).queryValue());
						map.put("balanceEnd", new AVP_Integer64(BalanceEnd).queryValue());
					}
					AVP balanceTypeFlag = returnPlanInfoGroup.find(90208, Constants.DIAMETER_VENDOR_CT);
					if (balanceTypeFlag != null) {//BalanceTypeFlag
						map.put("balanceTypeFlag", new AVP_Integer32(balanceTypeFlag).queryValue());
					}
					AVP balanceTypeName = returnPlanInfoGroup.find(50103, Constants.DIAMETER_VENDOR_CT);
					if (balanceTypeName != null) {//Balance_ItemType_Detail
						map.put("balanceTypeName", new AVP_UTF8String(balanceTypeName).queryValue());
					}
					AVP accNbrDetail  = returnPlanInfoGroup.find(90226, Constants.DIAMETER_VENDOR_CT);
					if (accNbrDetail  != null) {//AccNbrDetail
						map.put("accNbrDetail", new AVP_UTF8String(accNbrDetail).queryValue());
					}
					returnPlanInfos.add(map);
				}
			}
			resultMap.put("balanceChangeList", returnPlanInfos);
			
		} catch (InvalidAVPLengthException e) {
			resultMap = null;
			_log.error("getAvpsFromMessage is error：", e);
		}
		return resultMap;
	}
	
	/**
	 * 调用详单查询webservice接口
	 * @param param
	 * @return
	 */
	private String sendWebService(String param,String url) {
		_log.info("===========WebServiceProcessor url===============" + url);
		_log.info("===========WebServiceProcessor param===============" + param);
		String resp = "";
		PostMethod post = new PostMethod(url);
		try {
			RequestEntity requestEntity = new StringRequestEntity(param, "text/xml", "UTF-8");
			post.setRequestEntity(requestEntity);
			post.setRequestHeader("SOAPAction", "text/xml; charset=utf-8");
			HttpClient client = new HttpClient();
			client.getHttpConnectionManager().getParams().setConnectionTimeout(5 * 1000);
			client.getHttpConnectionManager().getParams().setSoTimeout(5000);
			client.executeMethod(post);
			resp = post.getResponseBodyAsString();
		} catch (UnsupportedEncodingException e) {
			_log.error("===========" + url + " call UnsupportedEncodingException===============", e);
		} catch (HttpException e) {
			_log.error("===========" + url + " call HttpException===============", e);
		} catch (IOException e) {
			_log.error("===========" + url + " call IOException===============", e);
		}
		_log.info("===========WebServiceProcessor resp===============" + resp);
		return resp;
	}
	
	/**
	 * 由于计费侧提供的接口协议没变，只是地址调整，割接到3.0的本地网需要调用新的地址
	 * 集团电子发票API接口调整
	 * 获取判断使用的地址
	 * jf3_flag 刷新开关  配置为1则表示启用割接地市判断，配置为0则表示按现有的流程
	 * Jf3_jt_latn_id  割接地市配置项（多个地市用逗号分隔，如果配置项调整为888，则表示全部调用新地址）
	 * resultLanIdStr 区域编码
	 * cityId
	 * jf3_jt_latn_id 是84201这种
		jf3_latn_id是1001 1018 这种
		jf3_area_coee是027 0716 这种
		type 传参0 1001类 传1 84210类   返参 1 新 0 旧的
	 */
	private String getVersionType(String cityId,String type) {
		String jf3_flag = userResourceConfigService.getValue("jf3_flag","");////增加刷新开关  ,配置为1则表示启用割接地市判断，配置为0则表示按现有的流程
		String jf3_jt_latn_id = userResourceConfigService.getValue("jf3_jt_latn_id","");
		String jf3_latn_id = userResourceConfigService.getValue("jf3_latn_id","");
		String str;
		if("0".equals(type)) {
			//1001类型
			str = jf3_latn_id;
		}else {
			//84201 类型
			str = jf3_jt_latn_id;
		}
		//1 新流程  0 旧的流程
		if("1".equals(jf3_flag)) {
			if("888".equals(str)) {
				return "1";//新的
			}else {
				String[] split_jt_latn_id = str.split(",");
				for (String string : split_jt_latn_id) {
					if(string.equals(cityId)) {
						//包含,仅区分新旧
						return "1";//新的 Recharged.jf3@027.ctnbc-bon.net
					}
				}
			}
			
		}
		return "0";//旧的 SeverRecharge.SGWPAY@027.ctnbc-bon.net  
	}
	
	private String getAreaCode(String homeAreaCode) {
		String [][]  arr1= {{"1001","027"},{"1003","0710"},{"1004","0713"},{"1005","0717"},{"1006","0712"},
				{"1007","0711"},{"1008","0715"},{"1009","0719"},{"1010","0724"},{"1011","0714"},{"1012","0722"},
				{"1013","0718"},{"1014","0728"},{"1015","0728"},{"1016","0728"},{"1017","0719"},{"1018","0716"}};
		for (String[] strings : arr1) {
			if(homeAreaCode.equals(strings[0])) {
				return strings[1];
			}
		}
		return "027";
	}
	public static void main(String[] args) {
		QueryBalanceResponse queryBalanceResponse = null;
		try{
			String resp = "";
			XStream xstream2 = new XStream(new DomDriver());
			xstream2.alias("QueryBalanceResponse", QueryBalanceResponse.class);
			xstream2.alias("balanceQuery", QueryBalanceResponse.BalanceQuery.class);
			xstream2.addImplicitCollection(QueryBalanceResponse.class, "balanceQuery");
			//xstream2.autodetectAnnotations(true);
			//resp = getRespString(resp);
			queryBalanceResponse = (QueryBalanceResponse) xstream2.fromXML(resp.substring(resp.indexOf("<QueryBalanceResponse"), resp.indexOf("</soapenv:Body>")));
		}catch(Exception e){
			_log.error("详单webservice调用异常：", e);
		}
		Gson gson = new Gson();
		String response = gson.toJson(queryBalanceResponse);
		System.out.println(response+"123");
	}
	
}
